home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume26 / shadow / part08 < prev    next >
Encoding:
Text File  |  1991-11-24  |  54.3 KB  |  2,423 lines

  1. Newsgroups: comp.sources.misc
  2. From: jfh@rpp386.Cactus.ORG (John F Haugh II)
  3. Subject:  v26i061:  shadow - Shadow Password Suite, Part08/11
  4. Message-ID: <1991Nov24.185207.20553@sparky.imd.sterling.com>
  5. X-Md4-Signature: a43c652bfff931c20d58afe8ef696479
  6. Date: Sun, 24 Nov 1991 18:52:07 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jfh@rpp386.Cactus.ORG (John F Haugh II)
  10. Posting-number: Volume 26, Issue 61
  11. Archive-name: shadow/part08
  12. Environment: UNIX
  13. Supersedes: shadow-2: Volume 06, Issue 22-24
  14.  
  15. #! /bin/sh
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  chpasswd.c dpmain.c faillog.c groupdel.c gshadow.c
  21. #   obscure.c pwconv.c setup.c sulogin.c useradd.1 utmp.c
  22. # Wrapped by kent@sparky on Sun Nov 24 11:03:43 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 8 (of 11)."'
  26. if test -f 'chpasswd.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'chpasswd.c'\"
  28. else
  29.   echo shar: Extracting \"'chpasswd.c'\" \(5160 characters\)
  30.   sed "s/^X//" >'chpasswd.c' <<'END_OF_FILE'
  31. X/*
  32. X * Copyright 1990, 1991, John F. Haugh II
  33. X * All rights reserved.
  34. X *
  35. X * Permission is granted to copy and create derivative works for any
  36. X * non-commercial purpose, provided this copyright notice is preserved
  37. X * in all copies of source code, or included in human readable form
  38. X * and conspicuously displayed on all copies of object code or
  39. X * distribution media.
  40. X *
  41. X * chpasswd - update passwords in batch
  42. X *
  43. X *    chpasswd reads standard input for a list of colon separated
  44. X *    user names and new passwords.  the appropriate password
  45. X *    files are updated to reflect the changes.  because the
  46. X *    changes are made in a batch fashion, the user must run
  47. X *    the mkpasswd command after this command terminates since
  48. X *    no password updates occur until the very end.
  49. X */
  50. X
  51. X#include <stdio.h>
  52. X#include "pwd.h"
  53. X#include <fcntl.h>
  54. X#include <string.h>
  55. X#include "config.h"
  56. X#ifdef    SHADOWPWD
  57. X#include "shadow.h"
  58. X#endif
  59. X
  60. X#ifndef    lint
  61. Xstatic    char    sccsid[] = "@(#)chpasswd.c    3.4    08:57:30    6/10/91";
  62. X#endif
  63. X
  64. Xchar    *Prog;
  65. X
  66. Xextern    char    *pw_encrypt();
  67. Xextern    char    *l64a();
  68. X
  69. X/* 
  70. X * If it weren't for the different structures and differences in how
  71. X * certain fields were manipulated, I could just use macros to replace
  72. X * the function calls for the different file formats.  So I make the
  73. X * best of things and just use macros to replace a few of the calls.
  74. X */
  75. X
  76. X#ifdef    SHADOWPWD
  77. X#define    pw_lock        spw_lock
  78. X#define    pw_open        spw_open
  79. X#define    pw_close    spw_close
  80. X#define    pw_unlock    spw_unlock
  81. X#endif
  82. X
  83. X/*
  84. X * usage - display usage message and exit
  85. X */
  86. X
  87. Xusage ()
  88. X{
  89. X    fprintf (stderr, "usage: %s\n", Prog);
  90. X    exit (1);
  91. X}
  92. X
  93. Xmain (argc, argv)
  94. Xint    argc;
  95. Xchar    **argv;
  96. X{
  97. X    char    buf[BUFSIZ];
  98. X    char    *name;
  99. X    char    *newpwd;
  100. X    char    *cp;
  101. X#ifdef    SHADOWPWD
  102. X    struct    spwd    *sp;
  103. X    struct    spwd    newsp;
  104. X    struct    spwd    *spw_locate();
  105. X#else
  106. X    struct    passwd    *pw;
  107. X    struct    passwd    newpw;
  108. X    struct    passwd    *pw_locate();
  109. X    char    newage[5];
  110. X#endif
  111. X    int    errors = 0;
  112. X    int    line = 0;
  113. X    long    now = time ((long *) 0) / (24L*3600L);
  114. X
  115. X    if (Prog = strrchr (argv[0], '/'))
  116. X        Prog++;
  117. X    else
  118. X        Prog = argv[0];
  119. X
  120. X    if (argc != 1)
  121. X        usage ();
  122. X
  123. X    /*
  124. X     * Lock the password file and open it for reading.  This will
  125. X     * bring all of the entries into memory where they may be
  126. X     * updated.
  127. X     */
  128. X
  129. X    if (! pw_lock ()) {
  130. X        fprintf (stderr, "%s: can't lock password file\n", Prog);
  131. X        exit (1);
  132. X    }
  133. X    if (! pw_open (O_RDWR)) {
  134. X        fprintf (stderr, "%s: can't open password file\n", Prog);
  135. X        exit (1);
  136. X    }
  137. X
  138. X    /*
  139. X     * Read each line, separating the user name from the password.
  140. X     * The password entry for each user will be looked up in the
  141. X     * appropriate file (shadow or passwd) and the password changed.
  142. X     * For shadow files the last change date is set directly, for
  143. X     * passwd files the last change date is set in the age only if
  144. X     * aging information is present.
  145. X     */
  146. X
  147. X    while (fgets (buf, sizeof buf, stdin) != (char *) 0) {
  148. X        line++;
  149. X        if (cp = strrchr (buf, '\n')) {
  150. X            *cp = '\0';
  151. X        } else {
  152. X            fprintf (stderr, "%s: line %d: line too long\n",
  153. X                Prog, line);
  154. X            errors++;
  155. X            continue;
  156. X        }
  157. X
  158. X        /*
  159. X         * The username is the first field.  It is separated
  160. X         * from the password with a ":" character which is
  161. X         * replaced with a NUL to give the new password.  The
  162. X         * new password will then be encrypted in the normal
  163. X         * fashion with a new salt generated.
  164. X         */
  165. X
  166. X        name = buf;
  167. X        if (cp = strchr (name, ':')) {
  168. X            *cp++ = '\0';
  169. X        } else {
  170. X            fprintf (stderr, "%s: line %d: missing new password\n",
  171. X                Prog, line);
  172. X            errors++;
  173. X            continue;
  174. X        }
  175. X        newpwd = cp;
  176. X        cp = pw_encrypt (newpwd, (char *) 0);
  177. X
  178. X        /*
  179. X         * Get the password file entry for this user.  The user
  180. X         * must already exist.
  181. X         */
  182. X
  183. X#ifdef    SHADOWPWD
  184. X        if (! (sp = spw_locate (name)))
  185. X#else
  186. X        if (! (pw = pw_locate (name)))
  187. X#endif
  188. X        {
  189. X            fprintf (stderr, "%s: line %d: unknown user %s\n",
  190. X                Prog, line, name);
  191. X            errors++;
  192. X            continue;
  193. X        }
  194. X
  195. X        /*
  196. X         * The freshly encrypted new password is merged into
  197. X         * the user's password file entry and the last password
  198. X         * change date is set to the current date.
  199. X         */
  200. X
  201. X#ifdef    SHADOWPWD
  202. X        newsp = *sp;
  203. X        newsp.sp_pwdp = cp;
  204. X        newsp.sp_lstchg = now;
  205. X#else
  206. X        newpw = *pw;
  207. X        newpw.pw_passwd = cp;
  208. X#ifdef    ATT_AGE
  209. X        if (newpw.pw_age[0]) {
  210. X            strcpy (newage, newpw.pw_age);
  211. X            strcpy (newage + 2, l64a (now / 7));
  212. X            newpw.pw_age = newage;
  213. X        }
  214. X#endif
  215. X#endif
  216. X
  217. X        /* 
  218. X         * The updated password file entry is then put back
  219. X         * and will be written to the password file later, after
  220. X         * all the other entries have been updated as well.
  221. X         */
  222. X
  223. X#ifdef    SHADOWPWD
  224. X        if (! spw_update (&newsp))
  225. X#else
  226. X        if (! pw_update (&newpw))
  227. X#endif
  228. X        {
  229. X            fprintf (stderr, "%s: line %d: cannot update password entry\n",
  230. X                Prog, line);
  231. X            errors++;
  232. X            continue;
  233. X        }
  234. X    }
  235. X
  236. X    /*
  237. X     * Any detected errors will cause the entire set of changes
  238. X     * to be aborted.  Unlocking the password file will cause
  239. X     * all of the changes to be ignored.  Otherwise the file is
  240. X     * closed, causing the changes to be written out all at
  241. X     * once, and then unlocked afterwards.
  242. X     */
  243. X
  244. X    if (errors) {
  245. X        fprintf (stderr, "%s: error detected, changes ignored\n", Prog);
  246. X        pw_unlock ();
  247. X        exit (1);
  248. X    }
  249. X    if (! pw_close ()) {
  250. X        fprintf (stderr, "%s: error updating password file\n", Prog);
  251. X        exit (1);
  252. X    }
  253. X    (void) pw_unlock ();
  254. X}
  255. END_OF_FILE
  256.   if test 5160 -ne `wc -c <'chpasswd.c'`; then
  257.     echo shar: \"'chpasswd.c'\" unpacked with wrong size!
  258.   fi
  259.   # end of 'chpasswd.c'
  260. fi
  261. if test -f 'dpmain.c' -a "${1}" != "-c" ; then 
  262.   echo shar: Will not clobber existing file \"'dpmain.c'\"
  263. else
  264.   echo shar: Extracting \"'dpmain.c'\" \(4250 characters\)
  265.   sed "s/^X//" >'dpmain.c' <<'END_OF_FILE'
  266. X/*
  267. X * Copyright 1990, 1991 John F. Haugh II
  268. X * All rights reserved.
  269. X *
  270. X * Permission is granted to copy and create derivative works for any
  271. X * non-commercial purpose, provided this copyright notice is preserved
  272. X * in all copies of source code, or included in human readable form
  273. X * and conspicuously displayed on all copies of object code or
  274. X * distribution media.
  275. X */
  276. X
  277. X#include <sys/types.h>
  278. X#include <sys/stat.h>
  279. X#include <stdio.h>
  280. X#include <fcntl.h>
  281. X#ifdef    BSD
  282. X#include <strings.h>
  283. X#else
  284. X#include <string.h>
  285. X#endif
  286. X#include "dialup.h"
  287. X
  288. X#ifndef    lint
  289. Xstatic    char    sccsid[] = "@(#)dpmain.c    3.4    17:31:55    8/4/91";
  290. X#endif
  291. X
  292. X#ifdef    USG
  293. X#define    bzero(p,l)    memset(p, 0, l)
  294. X#endif
  295. X
  296. X#define    DTMP    "/etc/d_passwd.tmp"
  297. X
  298. X/*
  299. X * Prompts and messages go here.
  300. X */
  301. X
  302. X#define    PASS1    "Shell password:"
  303. X#define    PASS2    "re-enter Shell password:"
  304. X#define    NOMATCH    "%s: Passwords do not match, try again.\n"
  305. X#define    NOFOUND    "%s: Shell %s not found.\n"
  306. X
  307. Xint    aflg;
  308. Xint    dflg;
  309. Xchar    *Prog;
  310. X
  311. Xextern    char    *pw_encrypt();
  312. Xextern    char    *getpass();
  313. X
  314. Xusage ()
  315. X{
  316. X    fprintf (stderr, "Usage: %s [ -(a|d) ] shell\n", Prog);
  317. X    exit (1);
  318. X}
  319. X
  320. Xmain (argc, argv)
  321. Xint    argc;
  322. Xchar    **argv;
  323. X{
  324. X    struct    dialup    *dial;
  325. X    struct    dialup    dent;
  326. X    struct    stat    sb;
  327. X    FILE    *fp;
  328. X    char    *shell;
  329. X    char    *cp;
  330. X    char    pass[BUFSIZ];
  331. X    int    fd;
  332. X    int    found = 0;
  333. X    int    opt;
  334. X    extern    int    optind;
  335. X    extern    char    *optarg;
  336. X
  337. X    if (Prog = strrchr (argv[0], '/'))
  338. X        Prog++;
  339. X    else
  340. X        Prog = argv[0];
  341. X
  342. X    while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
  343. X        switch (opt) {
  344. X            case 'a':
  345. X                aflg++;
  346. X                shell = optarg;
  347. X                break;
  348. X            case 'd':
  349. X                dflg++;
  350. X                shell = optarg;
  351. X                break;
  352. X            default:
  353. X                usage ();
  354. X        }
  355. X    }
  356. X    if (! aflg && ! dflg)
  357. X        aflg++;
  358. X
  359. X    if (! shell) {
  360. X        if (optind >= argc)
  361. X            usage ();
  362. X        else
  363. X            shell = argv[optind];
  364. X    }
  365. X    if (aflg + dflg != 1)
  366. X        usage ();
  367. X
  368. X    /*
  369. X     * Add a new shell to the password file, or update an existing
  370. X     * entry.  Begin by getting an encrypted password for this
  371. X     * shell.
  372. X     */
  373. X
  374. X    if (aflg) {
  375. X        int    tries = 3;
  376. X
  377. X        dent.du_shell = shell;
  378. X        dent.du_passwd = "";
  379. X
  380. Xagain:
  381. X        if (! (cp = getpass (PASS1)))
  382. X            exit (1);
  383. X
  384. X        strcpy (pass, cp);
  385. X        bzero (cp, strlen (cp));
  386. X
  387. X        if (! (cp = getpass (PASS2)))
  388. X            exit (1);
  389. X
  390. X        if (strcmp (pass, cp)) {
  391. X            bzero (pass, strlen (pass));
  392. X            bzero (cp, strlen (cp));
  393. X            fprintf (stderr, NOMATCH, Prog);
  394. X
  395. X            if (--tries)
  396. X                goto again;
  397. X
  398. X            exit (1);
  399. X        }
  400. X        bzero (cp, strlen (cp));
  401. X        dent.du_passwd = pw_encrypt (pass, (char *) 0);
  402. X        bzero (pass, strlen (pass));
  403. X    }
  404. X
  405. X    /*
  406. X     * Create the temporary file for the updated dialup password
  407. X     * information to be placed into.  Turn it into a (FILE *)
  408. X     * for use by putduent().
  409. X     */
  410. X
  411. X    if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
  412. X        sprintf (pass, "%s: can't create %s", Prog, DTMP);
  413. X        perror (pass);
  414. X        exit (1);
  415. X    }
  416. X    if (! (fp = fdopen (fd, "r+"))) {
  417. X        sprintf (pass, "%s: can't open %s", Prog, DTMP);
  418. X        perror (pass);
  419. X        exit (1);
  420. X    }
  421. X
  422. X    /*
  423. X     * Scan the dialup password file for the named entry,
  424. X     * copying out other entries along the way.  Copying
  425. X     * stops when a match is found or the file runs out.
  426. X     */
  427. X
  428. X    while (dial = getduent ()) {
  429. X        if (strcmp (dial->du_shell, shell) == 0) {
  430. X            found = 1;
  431. X            break;
  432. X        }
  433. X        if (putduent (dial, fp))
  434. X            goto failure;
  435. X    }
  436. X
  437. X    /*
  438. X     * To delete the entry, just don't copy it.  To update
  439. X     * the entry, output the modified version - works with
  440. X     * new entries as well.
  441. X     */
  442. X
  443. X    if (dflg && ! found) {
  444. X        fprintf (stderr, NOMATCH, Prog, shell);
  445. X        exit (1);
  446. X    }
  447. X    if (aflg)
  448. X        if (putduent (&dent, fp))
  449. X            goto failure;
  450. X
  451. X    /*
  452. X     * Now copy out the remaining entries.  Flush and close the
  453. X     * new file before doing anything nasty to the existing
  454. X     * file.
  455. X     */
  456. X
  457. X
  458. X    while (dial = getduent ())
  459. X        if (putduent (dial, fp))
  460. X            goto failure;
  461. X
  462. X    if (fflush (fp))
  463. X        goto failure;
  464. X
  465. X    fclose (fp);
  466. X
  467. X    /*
  468. X     * If the original file did not exist, we must create a new
  469. X     * file with owner "root" and mode 400.  Otherwise we copy
  470. X     * the modes from the existing file to the new file.
  471. X     *
  472. X     * After this is done the new file will replace the old file.
  473. X     */
  474. X
  475. X    if (! stat (DIALPWD, &sb)) {
  476. X        chown (DTMP, sb.st_uid, sb.st_gid);
  477. X        chmod (DTMP, sb.st_mode);
  478. X        unlink (DIALPWD);
  479. X    } else {
  480. X        chown (DTMP, 0, 0);
  481. X        chmod (DTMP, 0400);
  482. X    }
  483. X    link (DTMP, DIALPWD);
  484. X    unlink (DTMP);
  485. X
  486. X    sync ();
  487. X    exit (0);
  488. X
  489. Xfailure:
  490. X    unlink (DTMP);
  491. X    exit (1);
  492. X}
  493. END_OF_FILE
  494.   if test 4250 -ne `wc -c <'dpmain.c'`; then
  495.     echo shar: \"'dpmain.c'\" unpacked with wrong size!
  496.   fi
  497.   # end of 'dpmain.c'
  498. fi
  499. if test -f 'faillog.c' -a "${1}" != "-c" ; then 
  500.   echo shar: Will not clobber existing file \"'faillog.c'\"
  501. else
  502.   echo shar: Extracting \"'faillog.c'\" \(4879 characters\)
  503.   sed "s/^X//" >'faillog.c' <<'END_OF_FILE'
  504. X/*
  505. X * Copyright 1989, 1990, John F. Haugh II
  506. X * All rights reserved.
  507. X *
  508. X * Permission is granted to copy and create derivative works for any
  509. X * non-commercial purpose, provided this copyright notice is preserved
  510. X * in all copies of source code, or included in human readable form
  511. X * and conspicuously displayed on all copies of object code or
  512. X * distribution media.
  513. X */
  514. X
  515. X#include <sys/types.h>
  516. X#include <sys/stat.h>
  517. X#include <stdio.h>
  518. X#include "pwd.h"
  519. X#include <time.h>
  520. X#ifndef    BSD
  521. X#include <string.h>
  522. X#include <memory.h>
  523. X#else
  524. X#include <strings.h>
  525. X#define    strchr    index
  526. X#define    strrchr    rindex
  527. X#endif
  528. X#include "config.h"
  529. X#include "faillog.h"
  530. X
  531. X#ifndef    lint
  532. Xstatic    char    _sccsid[] = "@(#)faillog.c    3.2    08:44:11    9/12/91";
  533. X#endif
  534. X
  535. XFILE    *fail;        /* failure file stream */
  536. Xoff_t    user;        /* one single user, specified on command line */
  537. Xint    days;        /* number of days to consider for print command */
  538. Xtime_t    seconds;    /* that number of days in seconds */
  539. Xint    max;        /* maximum failure count for fail_max */
  540. X
  541. Xint    uflg;        /* set if user is a valid user id */
  542. Xint    tflg;        /* print is restricted to most recent days */
  543. Xstruct    faillog    faillog; /* scratch structure to play with ... */
  544. Xstruct    stat    statbuf; /* fstat buffer for file size */
  545. X
  546. Xextern    int    optind;
  547. Xextern    char    *optarg;
  548. Xextern    char    *asctime ();
  549. Xextern    struct    passwd    *getpwuid ();
  550. Xextern    struct    passwd    *getpwnam ();
  551. Xextern    struct    passwd    *getpwent ();
  552. Xextern    struct    tm    *localtime ();
  553. X
  554. X#define    DAY    (24L*3600L)
  555. X#define    NOW    (time ((time_t *) 0))
  556. X
  557. Xmain (argc, argv)
  558. Xint    argc;
  559. Xchar    **argv;
  560. X{
  561. X    char    *mode;
  562. X    int    c;
  563. X    struct    passwd    *pwent;
  564. X
  565. X    if (getuid () == 0)    /* only root can update anything */
  566. X        mode = "r+";
  567. X    else            /* all others can only look */
  568. X        mode = "r";
  569. X
  570. X    if ((fail = fopen (FAILFILE, mode)) == (FILE *) 0) {
  571. X        perror (FAILFILE);
  572. X        exit (1);
  573. X    }
  574. X    while ((c = getopt (argc, argv, "m:pru:t:")) != EOF) {
  575. X        switch (c) {
  576. X            case 'm':
  577. X                max = atoi (optarg);
  578. X                setmax ();
  579. X                break;
  580. X            case 'p':
  581. X                print ();
  582. X                break;
  583. X            case 'r':
  584. X                reset ();
  585. X                break;
  586. X            case 'u':
  587. X                pwent = getpwnam (optarg);
  588. X                if (! pwent) {
  589. X                    fprintf (stderr, "Unknown User: %s\n", optarg);
  590. X                    exit (1);
  591. X                }
  592. X                uflg++;
  593. X                user = pwent->pw_uid;
  594. X                break;
  595. X            case 't':
  596. X                days = atoi (optarg);
  597. X                seconds = days * DAY;
  598. X                tflg++;
  599. X                break;
  600. X        }
  601. X    }
  602. X    fclose (fail);
  603. X    exit (0);
  604. X    /*NOTREACHED*/
  605. X}
  606. X
  607. Xprint ()
  608. X{
  609. X    int    uid;
  610. X    off_t    offset;
  611. X
  612. X    if (uflg) {
  613. X        offset = user * sizeof faillog;
  614. X        fstat (fileno (fail), &statbuf);
  615. X        if (offset >= statbuf.st_size)
  616. X            return;
  617. X
  618. X        fseek (fail, (off_t) user * sizeof faillog, 0);
  619. X        if (fread ((char *) &faillog, sizeof faillog, 1, fail) == 1)
  620. X            print_one (&faillog, user);
  621. X        else
  622. X            perror (FAILFILE);
  623. X    } else {
  624. X        for (uid = 0;
  625. X            fread ((char *) &faillog, sizeof faillog, 1, fail) == 1;
  626. X                uid++) {
  627. X
  628. X            if (faillog.fail_cnt == 0)
  629. X                continue;
  630. X
  631. X            if (tflg && NOW - faillog.fail_time > seconds)
  632. X                continue;
  633. X
  634. X            print_one (&faillog, uid);
  635. X        }
  636. X    }
  637. X}
  638. X
  639. Xprint_one (uid)
  640. Xint    uid;
  641. X{
  642. X    static    int    once;
  643. X    char    *cp;
  644. X    struct    tm    *tm;
  645. X    struct    passwd    *pwent;
  646. X
  647. X    if (! once) {
  648. X        printf ("Username        Failures    Maximum     Latest\n");
  649. X        once++;
  650. X    }
  651. X    pwent = getpwuid (uid);
  652. X    tm = localtime (&faillog.fail_time);
  653. X    cp = asctime (tm);
  654. X    cp[24] = '\0';
  655. X
  656. X    if (pwent) {
  657. X        printf ("%-16s    %4d       %4d",
  658. X            pwent->pw_name, faillog.fail_cnt, faillog.fail_max);
  659. X        if (faillog.fail_time)
  660. X            printf ("     %s on %s\n", cp, faillog.fail_line);
  661. X        else
  662. X            putchar ('\n');
  663. X    }
  664. X}
  665. X
  666. Xreset ()
  667. X{
  668. X    int    uid = 0;
  669. X
  670. X    if (uflg)
  671. X        reset_one (user);
  672. X    else
  673. X        for (uid = 0;reset_one (uid);uid++)
  674. X            ;
  675. X}
  676. X
  677. Xreset_one (uid)
  678. Xint    uid;
  679. X{
  680. X    off_t    offset;
  681. X
  682. X    offset = uid * sizeof faillog;
  683. X    fstat (fileno (fail), &statbuf);
  684. X    if (offset >= statbuf.st_size)
  685. X        return (0);
  686. X
  687. X    if (fseek (fail, offset, 0) != 0) {
  688. X        perror (FAILFILE);
  689. X        return (0);
  690. X    }
  691. X    if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
  692. X        if (! feof (fail))
  693. X            perror (FAILFILE);
  694. X
  695. X        return (0);
  696. X    }
  697. X    if (faillog.fail_cnt == 0)
  698. X        return (1);    /* don't fill in no holes ... */
  699. X
  700. X    faillog.fail_cnt = 0;
  701. X
  702. X    if (fseek (fail, offset, 0) == 0
  703. X        && fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1) {
  704. X        fflush (fail);
  705. X        return (1);
  706. X    } else {
  707. X        perror (FAILFILE);
  708. X    }
  709. X    return (0);
  710. X}
  711. X
  712. Xsetmax ()
  713. X{
  714. X    struct    passwd    *pwent;
  715. X
  716. X    if (uflg) {
  717. X        setmax_one (user);
  718. X    } else {
  719. X        setpwent ();
  720. X        while (pwent = getpwent ())
  721. X            setmax_one (pwent->pw_uid);
  722. X    }
  723. X}
  724. X
  725. Xsetmax_one (uid)
  726. Xint    uid;
  727. X{
  728. X    off_t    offset;
  729. X
  730. X    offset = uid * sizeof faillog;
  731. X
  732. X    if (fseek (fail, offset, 0) != 0) {
  733. X        perror (FAILFILE);
  734. X        return;
  735. X    }
  736. X    if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
  737. X        if (! feof (fail))
  738. X            perror (FAILFILE);
  739. X    } else {
  740. X#ifndef    BSD
  741. X        memset ((char *) &faillog, '\0', sizeof faillog);
  742. X#else
  743. X        bzero ((char *) &faillog, sizeof faillog);
  744. X#endif
  745. X    }
  746. X    faillog.fail_max = max;
  747. X
  748. X    if (fseek (fail, offset, 0) == 0
  749. X        && fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1)
  750. X        fflush (fail);
  751. X    else
  752. X        perror (FAILFILE);
  753. X}
  754. END_OF_FILE
  755.   if test 4879 -ne `wc -c <'faillog.c'`; then
  756.     echo shar: \"'faillog.c'\" unpacked with wrong size!
  757.   fi
  758.   # end of 'faillog.c'
  759. fi
  760. if test -f 'groupdel.c' -a "${1}" != "-c" ; then 
  761.   echo shar: Will not clobber existing file \"'groupdel.c'\"
  762. else
  763.   echo shar: Extracting \"'groupdel.c'\" \(4494 characters\)
  764.   sed "s/^X//" >'groupdel.c' <<'END_OF_FILE'
  765. X/*
  766. X * Copyright 1991, John F. Haugh II
  767. X * All rights reserved.
  768. X *
  769. X * Permission is granted to copy and create derivative works for any
  770. X * non-commercial purpose, provided this copyright notice is preserved
  771. X * in all copies of source code, or included in human readable form
  772. X * and conspicuously displayed on all copies of object code or
  773. X * distribution media.
  774. X */
  775. X
  776. X#ifndef lint
  777. Xstatic    char    sccsid[] = "@(#)groupdel.c    3.3    08:43:48    9/12/91";
  778. X#endif
  779. X
  780. X#include <sys/types.h>
  781. X#include <stdio.h>
  782. X#include <grp.h>
  783. X#include <ctype.h>
  784. X#include <fcntl.h>
  785. X
  786. X#ifdef    BSD
  787. X#include <strings.h>
  788. X#else
  789. X#include <string.h>
  790. X#endif
  791. X
  792. X#include "config.h"
  793. X#include "shadow.h"
  794. X
  795. X#ifdef    USE_SYSLOG
  796. X#include <syslog.h>
  797. X#endif
  798. X
  799. Xchar    group_name[BUFSIZ];
  800. Xchar    *Prog;
  801. X
  802. X#ifdef    NDBM
  803. Xextern    int    gr_dbm_mode;
  804. Xextern    int    sg_dbm_mode;
  805. X#endif
  806. Xextern    char    *malloc();
  807. X
  808. Xextern    struct    group    *getgrnam();
  809. Xextern    int    gr_lock();
  810. Xextern    int    gr_unlock();
  811. Xextern    int    gr_open();
  812. X
  813. X#ifdef    SHADOWGRP
  814. Xextern    int    sgr_lock();
  815. Xextern    int    sgr_unlock();
  816. Xextern    int    sgr_open();
  817. X#endif
  818. X
  819. X/*
  820. X * usage - display usage message and exit
  821. X */
  822. X
  823. Xusage ()
  824. X{
  825. X    fprintf (stderr, "usage: groupmod group\n");
  826. X    exit (2);
  827. X}
  828. X
  829. X/*
  830. X * grp_update - update group file entries
  831. X *
  832. X *    grp_update() writes the new records to the group files.
  833. X */
  834. X
  835. Xvoid
  836. Xgrp_update ()
  837. X{
  838. X    struct    group    *ogrp;
  839. X
  840. X    if (! gr_remove (group_name)) {
  841. X        fprintf (stderr, "%s: error removing group entry\n", Prog);
  842. X        exit (1);
  843. X    }
  844. X#ifdef    NDBM
  845. X
  846. X    /*
  847. X     * Update the DBM group file
  848. X     */
  849. X
  850. X    if (access ("/etc/group.pag", 0) == 0) {
  851. X        if ((ogrp = getgrnam (group_name)) &&
  852. X                ! gr_dbm_remove (ogrp)) {
  853. X            fprintf (stderr, "%s: error removing group dbm entry\n",
  854. X                Prog);
  855. X            exit (1);
  856. X        }
  857. X    }
  858. X    endgrent ();
  859. X#endif    /* NDBM */
  860. X
  861. X#ifdef    SHADOWGRP
  862. X
  863. X    /*
  864. X     * Delete the shadow group entries as well.
  865. X     */
  866. X
  867. X    if (! sgr_remove (group_name)) {
  868. X        fprintf (stderr, "%s: error removing shadow group entry\n",
  869. X            Prog);
  870. X        exit (1);
  871. X    }
  872. X#ifdef    NDBM
  873. X
  874. X    /*
  875. X     * Update the DBM shadow group file
  876. X     */
  877. X
  878. X    if (access ("/etc/gshadow.pag", 0) == 0) {
  879. X        if (! sgr_dbm_remove (group_name)) {
  880. X            fprintf (stderr,
  881. X                "%s: error removing shadow group dbm entry\n",
  882. X                Prog);
  883. X            exit (1);
  884. X        }
  885. X    }
  886. X    endsgent ();
  887. X#endif    /* NDBM */
  888. X#endif    /* SHADOWGRP */
  889. X#ifdef    USE_SYSLOG
  890. X    syslog (LOG_INFO, "remove group `%s'\n", group_name);
  891. X#endif    /* USE_SYSLOG */
  892. X}
  893. X
  894. X/*
  895. X * close_files - close all of the files that were opened
  896. X *
  897. X *    close_files() closes all of the files that were opened for this
  898. X *    new group.  This causes any modified entries to be written out.
  899. X */
  900. X
  901. Xclose_files ()
  902. X{
  903. X    if (! gr_close ()) {
  904. X        fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
  905. X        exit (1);
  906. X    }
  907. X    (void) gr_unlock ();
  908. X#ifdef    SHADOWGRP
  909. X    if (! sgr_close ()) {
  910. X        fprintf (stderr, "%s: cannot rewrite shadow group file\n",
  911. X            Prog);
  912. X        exit (1);
  913. X    }
  914. X    (void) sgr_unlock ();
  915. X#endif    /* SHADOWGRP */
  916. X}
  917. X
  918. X/*
  919. X * open_files - lock and open the group files
  920. X *
  921. X *    open_files() opens the two group files.
  922. X */
  923. X
  924. Xopen_files ()
  925. X{
  926. X    if (! gr_lock ()) {
  927. X        fprintf (stderr, "%s: unable to lock group file\n", Prog);
  928. X        exit (1);
  929. X    }
  930. X    if (! gr_open (O_RDWR)) {
  931. X        fprintf (stderr, "%s: unable to open group file\n", Prog);
  932. X        exit (1);
  933. X    }
  934. X#ifdef    SHADOWGRP
  935. X    if (! sgr_lock ()) {
  936. X        fprintf (stderr, "%s: unable to lock shadow group file\n",
  937. X            Prog);
  938. X        exit (1);
  939. X    }
  940. X    if (! sgr_open (O_RDWR)) {
  941. X        fprintf (stderr, "%s: unable to open shadow group file\n",
  942. X            Prog);
  943. X        exit (1);
  944. X    }
  945. X#endif    /* SHADOWGRP */
  946. X}
  947. X
  948. X/*
  949. X * main - groupdel command
  950. X *
  951. X *    The syntax of the groupdel command is
  952. X *    
  953. X *    groupdel group
  954. X *
  955. X *    The named group will be deleted.
  956. X */
  957. X
  958. Xmain (argc, argv)
  959. Xint    argc;
  960. Xchar    **argv;
  961. X{
  962. X
  963. X    /*
  964. X     * Get my name so that I can use it to report errors.
  965. X     */
  966. X
  967. X    if (Prog = strrchr (argv[0], '/'))
  968. X        Prog++;
  969. X    else
  970. X        Prog = argv[0];
  971. X
  972. X    if (argc != 2)
  973. X        usage ();
  974. X
  975. X    strncpy (group_name, argv[1], BUFSIZ);
  976. X
  977. X#ifdef    USE_SYSLOG
  978. X    openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
  979. X#endif    /* USE_SYSLOG */
  980. X
  981. X    /*
  982. X     * The open routines for the DBM files don't use read-write
  983. X     * as the mode, so we have to clue them in.
  984. X     */
  985. X
  986. X#ifdef    NDBM
  987. X    gr_dbm_mode = O_RDWR;
  988. X#ifdef    SHADOWGRP
  989. X    sg_dbm_mode = O_RDWR;
  990. X#endif    /* SHADOWGRP */
  991. X#endif    /* NDBM */
  992. X
  993. X    /*
  994. X     * Start with a quick check to see if the group exists.
  995. X     */
  996. X
  997. X    if (! getgrnam (group_name)) {
  998. X        fprintf (stderr, "%s: group %s does not exist\n",
  999. X            Prog, group_name);
  1000. X        exit (9);
  1001. X    }
  1002. X
  1003. X    /*
  1004. X     * Do the hard stuff - open the files, delete the group entries,
  1005. X     * then close and update the files.
  1006. X     */
  1007. X
  1008. X    open_files ();
  1009. X
  1010. X    grp_update ();
  1011. X
  1012. X    close_files ();
  1013. X    exit (0);
  1014. X    /*NOTREACHED*/
  1015. X}
  1016. END_OF_FILE
  1017.   if test 4494 -ne `wc -c <'groupdel.c'`; then
  1018.     echo shar: \"'groupdel.c'\" unpacked with wrong size!
  1019.   fi
  1020.   # end of 'groupdel.c'
  1021. fi
  1022. if test -f 'gshadow.c' -a "${1}" != "-c" ; then 
  1023.   echo shar: Will not clobber existing file \"'gshadow.c'\"
  1024. else
  1025.   echo shar: Extracting \"'gshadow.c'\" \(4592 characters\)
  1026.   sed "s/^X//" >'gshadow.c' <<'END_OF_FILE'
  1027. X/*
  1028. X * Copyright 1990, 1991, John F. Haugh II
  1029. X * All rights reserved.
  1030. X *
  1031. X * Permission is granted to copy and create derivative works for any
  1032. X * non-commercial purpose, provided this copyright notice is preserved
  1033. X * in all copies of source code, or included in human readable form
  1034. X * and conspicuously displayed on all copies of object code or
  1035. X * distribution media.
  1036. X */
  1037. X
  1038. X#include "shadow.h"
  1039. X#include "config.h"
  1040. X#include <stdio.h>
  1041. X#ifndef    BSD
  1042. X#include <string.h>
  1043. X#include <memory.h>
  1044. X#else
  1045. X#include <strings.h>
  1046. X#define    strchr    index
  1047. X#define    strrchr    rindex
  1048. X#endif
  1049. X
  1050. X#ifdef    NDBM
  1051. X#include <ndbm.h>
  1052. X#include <fcntl.h>
  1053. XDBM    *sgr_dbm;
  1054. Xint    sg_dbm_mode = -1;
  1055. Xstatic    int    dbmopened;
  1056. Xstatic    int    dbmerror;
  1057. X#endif
  1058. X
  1059. X
  1060. X#ifndef    lint
  1061. Xstatic    char    sccsid[] = "@(#)gshadow.c    3.7    08:45:58    9/12/91";
  1062. X#endif
  1063. X
  1064. X#define    MAXMEM    1024
  1065. X
  1066. Xstatic    FILE    *shadow;
  1067. Xstatic    char    *sgrpfile = "/etc/gshadow";
  1068. Xstatic    char    sgrbuf[BUFSIZ*4];
  1069. Xstatic    char    *members[MAXMEM+1];
  1070. Xstatic    char    *admins[MAXMEM+1];
  1071. Xstatic    struct    sgrp    sgroup;
  1072. X
  1073. Xextern    char    *fgetsx();
  1074. Xextern    int    fputsx();
  1075. X
  1076. X#define    FIELDS    4
  1077. X
  1078. Xstatic char **
  1079. Xlist (s, l)
  1080. Xchar    *s;
  1081. Xchar    **l;
  1082. X{
  1083. X    int    nmembers = 0;
  1084. X
  1085. X    while (s && *s) {
  1086. X        l[nmembers++] = s;
  1087. X        if (s = strchr (s, ','))
  1088. X            *s++ = '\0';
  1089. X    }
  1090. X    l[nmembers] = (char *) 0;
  1091. X    return l;
  1092. X}
  1093. X
  1094. Xvoid
  1095. Xsetsgent ()
  1096. X{
  1097. X#ifdef    NDBM
  1098. X    int    mode;
  1099. X#endif    /* NDBM */
  1100. X
  1101. X    if (shadow)
  1102. X        rewind (shadow);
  1103. X    else
  1104. X        shadow = fopen (GSHADOW, "r");
  1105. X
  1106. X    /*
  1107. X     * Attempt to open the DBM files if they have never been opened
  1108. X     * and an error has never been returned.
  1109. X     */
  1110. X
  1111. X#ifdef NDBM
  1112. X    if (! dbmerror && ! dbmopened) {
  1113. X        char    dbmfiles[BUFSIZ];
  1114. X
  1115. X        strcpy (dbmfiles, sgrpfile);
  1116. X        strcat (dbmfiles, ".pag");
  1117. X
  1118. X        if (sg_dbm_mode == -1)
  1119. X            mode = O_RDWR;
  1120. X        else
  1121. X            mode = (sg_dbm_mode == O_RDWR) ? O_RDWR:O_RDONLY;
  1122. X
  1123. X        if (access (dbmfiles, 0) ||
  1124. X            (! (sgr_dbm = dbm_open (sgrpfile, mode, 0))))
  1125. X            dbmerror = 1;
  1126. X        else
  1127. X            dbmopened = 1;
  1128. X    }
  1129. X#endif    /* NDBM */
  1130. X}
  1131. X
  1132. Xvoid
  1133. Xendsgent ()
  1134. X{
  1135. X    if (shadow)
  1136. X        (void) fclose (shadow);
  1137. X
  1138. X    shadow = (FILE *) 0;
  1139. X#ifdef    NDBM
  1140. X    if (dbmopened && sgr_dbm) {
  1141. X        dbm_close (sgr_dbm);
  1142. X        dbmopened = 0;
  1143. X        sgr_dbm = 0;
  1144. X    }
  1145. X#endif
  1146. X}
  1147. X
  1148. Xstruct sgrp *
  1149. Xsgetsgent (string)
  1150. Xchar    *string;
  1151. X{
  1152. X    char    *fields[FIELDS];
  1153. X    char    *cp;
  1154. X    int    atoi ();
  1155. X    long    atol ();
  1156. X    int    i;
  1157. X
  1158. X    strncpy (sgrbuf, string, (int) sizeof sgrbuf - 1);
  1159. X    sgrbuf[sizeof sgrbuf - 1] = '\0';
  1160. X
  1161. X    if (cp = strrchr (sgrbuf, '\n'))
  1162. X        *cp = '\0';
  1163. X
  1164. X    for (cp = sgrbuf, i = 0;i < FIELDS && cp;i++) {
  1165. X        fields[i] = cp;
  1166. X        if (cp = strchr (cp, ':'))
  1167. X            *cp++ = '\0';
  1168. X    }
  1169. X    if (*cp || i != FIELDS)
  1170. X        return 0;
  1171. X
  1172. X    sgroup.sg_name = fields[0];
  1173. X    sgroup.sg_passwd = fields[1];
  1174. X    sgroup.sg_adm = list (fields[2], admins);
  1175. X    sgroup.sg_mem = list (fields[3], members);
  1176. X
  1177. X    return &sgroup;
  1178. X}
  1179. X
  1180. Xstruct sgrp
  1181. X*fgetsgent (fp)
  1182. XFILE    *fp;
  1183. X{
  1184. X    char    buf[sizeof sgrbuf];
  1185. X
  1186. X    if (! fp)
  1187. X        return (0);
  1188. X
  1189. X    if (fgetsx (buf, sizeof buf, fp) == (char *) 0)
  1190. X        return (0);
  1191. X
  1192. X    return sgetsgent (buf);
  1193. X}
  1194. X
  1195. Xstruct sgrp
  1196. X*getsgent ()
  1197. X{
  1198. X    if (! shadow)
  1199. X        setsgent ();
  1200. X
  1201. X    return (fgetsgent (shadow));
  1202. X}
  1203. X
  1204. Xstruct sgrp *
  1205. Xgetsgnam (name)
  1206. Xchar    *name;
  1207. X{
  1208. X    struct    sgrp    *sgrp;
  1209. X#ifdef NDBM
  1210. X    datum    key;
  1211. X    datum    content;
  1212. X#endif
  1213. X
  1214. X    setsgent ();
  1215. X
  1216. X#ifdef NDBM
  1217. X
  1218. X    /*
  1219. X     * If the DBM file are now open, create a key for this group and
  1220. X     * try to fetch the entry from the database.  A matching record
  1221. X     * will be unpacked into a static structure and returned to
  1222. X     * the user.
  1223. X     */
  1224. X
  1225. X    if (dbmopened) {
  1226. X        key.dsize = strlen (name);
  1227. X        key.dptr = name;
  1228. X
  1229. X        content = dbm_fetch (sgr_dbm, key);
  1230. X        if (content.dptr != 0) {
  1231. X            memcpy (sgrbuf, content.dptr, content.dsize);
  1232. X            sgroup.sg_mem = members;
  1233. X            sgroup.sg_adm = admins;
  1234. X            sgr_unpack (sgrbuf, content.dsize, &sgroup);
  1235. X            return &sgroup;
  1236. X        }
  1237. X    }
  1238. X#endif
  1239. X    while ((sgrp = getsgent ()) != (struct sgrp *) 0) {
  1240. X        if (strcmp (name, sgrp->sg_name) == 0)
  1241. X            return (sgrp);
  1242. X    }
  1243. X    return (0);
  1244. X}
  1245. X
  1246. Xint
  1247. Xputsgent (sgrp, fp)
  1248. Xstruct    sgrp    *sgrp;
  1249. XFILE    *fp;
  1250. X{
  1251. X    char    buf[sizeof sgrbuf];
  1252. X    char    *cp = buf;
  1253. X    int    i;
  1254. X
  1255. X    if (! fp || ! sgrp)
  1256. X        return -1;
  1257. X
  1258. X    /*
  1259. X     * Copy the group name and passwd.
  1260. X     */
  1261. X
  1262. X    strcpy (cp, sgrp->sg_name);
  1263. X    cp += strlen (cp);
  1264. X    *cp++ = ':';
  1265. X
  1266. X    strcpy (cp, sgrp->sg_passwd);
  1267. X    cp += strlen (cp);
  1268. X    *cp++ = ':';
  1269. X
  1270. X    /*
  1271. X     * Copy the administrators, separating each from the other
  1272. X     * with a ",".
  1273. X     */
  1274. X
  1275. X    for (i = 0;sgrp->sg_adm[i];i++) {
  1276. X        if (i > 0)
  1277. X            *cp++ = ',';
  1278. X
  1279. X        strcpy (cp, sgrp->sg_adm[i]);
  1280. X        cp += strlen (cp);
  1281. X    }
  1282. X    *cp++ = ':';
  1283. X
  1284. X    /*
  1285. X     * Now do likewise with the group members.
  1286. X     */
  1287. X
  1288. X    for (i = 0;sgrp->sg_mem[i];i++) {
  1289. X        if (i > 0)
  1290. X            *cp++ = ',';
  1291. X
  1292. X        strcpy (cp, sgrp->sg_mem[i]);
  1293. X        cp += strlen (cp);
  1294. X    }
  1295. X    *cp++ = '\n';
  1296. X    *cp = '\0';
  1297. X
  1298. X    /*
  1299. X     * Output using the function which understands the line
  1300. X     * continuation conventions.
  1301. X     */
  1302. X
  1303. X    return fputsx (buf, fp);
  1304. X}
  1305. END_OF_FILE
  1306.   if test 4592 -ne `wc -c <'gshadow.c'`; then
  1307.     echo shar: \"'gshadow.c'\" unpacked with wrong size!
  1308.   fi
  1309.   # end of 'gshadow.c'
  1310. fi
  1311. if test -f 'obscure.c' -a "${1}" != "-c" ; then 
  1312.   echo shar: Will not clobber existing file \"'obscure.c'\"
  1313. else
  1314.   echo shar: Extracting \"'obscure.c'\" \(3472 characters\)
  1315.   sed "s/^X//" >'obscure.c' <<'END_OF_FILE'
  1316. X/*
  1317. X * Copyright 1989, 1990, 1991, John F. Haugh II
  1318. X * All rights reserved.
  1319. X *
  1320. X * Permission is granted to copy and create derivative works for any
  1321. X * non-commercial purpose, provided this copyright notice is preserved
  1322. X * in all copies of source code, or included in human readable form
  1323. X * and conspicuously displayed on all copies of object code or
  1324. X * distribution media.
  1325. X */
  1326. X
  1327. X#include <ctype.h>
  1328. X#ifndef    BSD
  1329. X#include <string.h>
  1330. X#include <memory.h>
  1331. X#else
  1332. X#include <strings.h>
  1333. X#define    strchr    index
  1334. X#define    strrchr    rindex
  1335. X#endif
  1336. X#include "config.h"
  1337. X
  1338. X#ifndef    lint
  1339. Xstatic    char    sccsid[] = "@(#)obscure.c    3.5    07:43:55    9/17/91";
  1340. X#endif
  1341. X
  1342. Xextern    int    getdef_bool();
  1343. Xextern    int    getdef_num();
  1344. X
  1345. X#ifdef    NEED_STRSTR
  1346. X/*
  1347. X * strstr - find substring in string
  1348. X */
  1349. X
  1350. Xchar *
  1351. Xstrstr (string, pattern)
  1352. Xchar    *string;
  1353. Xchar    *pattern;
  1354. X{
  1355. X    char    *cp;
  1356. X    int    len;
  1357. X
  1358. X    len = strlen (pattern);
  1359. X
  1360. X    for (cp = string;cp = strchr (cp, *pattern);) {
  1361. X        if (strncmp (cp, pattern, len) == 0)
  1362. X            return cp;
  1363. X
  1364. X        cp++;
  1365. X    }
  1366. X    return 0;
  1367. X}
  1368. X#endif
  1369. X
  1370. X/*
  1371. X * Obscure - see if password is obscure enough.
  1372. X *
  1373. X *    The programmer is encouraged to add as much complexity to this
  1374. X *    routine as desired.  Included are some of my favorite ways to
  1375. X *    check passwords.
  1376. X */
  1377. X
  1378. X/*ARGSUSED*/
  1379. Xint    obscure (old, new)
  1380. Xchar    *old;
  1381. Xchar    *new;
  1382. X{
  1383. X    int    i;
  1384. X    char    oldmono[32];
  1385. X    char    newmono[32];
  1386. X    char    wrapped[64];
  1387. X
  1388. X    if (old[0] == '\0')
  1389. X        return (1);
  1390. X
  1391. X    if ( strlen(new) < getdef_num("PASS_MIN_LEN", 0) ) {
  1392. X        printf ("Too short.  ");
  1393. X        return (0);
  1394. X    }
  1395. X
  1396. X    /*
  1397. X     * Remaining checks are optional.
  1398. X     */
  1399. X    if ( !getdef_bool("OBSCURE_CHECKS_ENAB") )
  1400. X        return (1);
  1401. X
  1402. X    for (i = 0;new[i];i++)
  1403. X        newmono[i] = tolower (new[i]);
  1404. X
  1405. X    for (i = 0;old[i];i++)
  1406. X        oldmono[i] = tolower (old[i]); 
  1407. X
  1408. X    if (strcmp (new, old) == 0) {    /* the same */
  1409. X        printf ("No Change.  ");
  1410. X        return (0);
  1411. X    }
  1412. X    if (palindrome (newmono, oldmono))    /* a palindrome */
  1413. X        return (0);
  1414. X
  1415. X    if (strcmp (newmono, oldmono) == 0) {    /* case shifted */
  1416. X        printf ("Case changes only.  ");
  1417. X        return (0);
  1418. X    }
  1419. X    if (similiar (newmono, oldmono))    /* jumbled version */
  1420. X        return (0);
  1421. X
  1422. X    if (simple (old, new))            /* keyspace size */
  1423. X        return (0);
  1424. X
  1425. X    strcpy (wrapped, oldmono);
  1426. X    strcat (wrapped, oldmono);
  1427. X    if (strstr (wrapped, newmono)) {
  1428. X        printf ("Rotated.  ");
  1429. X        return (0);
  1430. X    }
  1431. X    return (1);
  1432. X}
  1433. X
  1434. X/*
  1435. X * can't be a palindrome - like `R A D A R' or `M A D A M'
  1436. X */
  1437. X
  1438. X/*ARGSUSED*/
  1439. Xint    palindrome (old, new)
  1440. Xchar    *old;
  1441. Xchar    *new;
  1442. X{
  1443. X    int    i, j;
  1444. X
  1445. X    i = strlen (new);
  1446. X
  1447. X    for (j = 0;j < i;j++)
  1448. X        if (new[i - j - 1] != new[j])
  1449. X            return (0);
  1450. X
  1451. X    printf ("A palindrome.  ");
  1452. X    return (1);
  1453. X}
  1454. X
  1455. X/*
  1456. X * more than half of the characters are different ones.
  1457. X */
  1458. X
  1459. X/*ARGSUSED*/
  1460. Xint    similiar (old, new)
  1461. Xchar    *old;
  1462. Xchar    *new;
  1463. X{
  1464. X    int    i, j;
  1465. X    char    *strchr ();
  1466. X
  1467. X    for (i = j = 0;new[i] && old[i];i++)
  1468. X        if (strchr (new, tolower (old[i])))
  1469. X            j++;
  1470. X
  1471. X    if (i >= j * 2)
  1472. X        return (0);
  1473. X
  1474. X    printf ("Too similiar.  ");
  1475. X    return (1);
  1476. X}
  1477. X
  1478. X/*
  1479. X * a nice mix of characters.
  1480. X */
  1481. X
  1482. X/*ARGSUSED*/
  1483. Xint    simple (old, new)
  1484. Xchar    *old;
  1485. Xchar    *new;
  1486. X{
  1487. X    int    digits = 0;
  1488. X    int    uppers = 0;
  1489. X    int    lowers = 0;
  1490. X    int    others = 0;
  1491. X    int    size;
  1492. X    int    i;
  1493. X
  1494. X    for (i = 0;new[i];i++) {
  1495. X        if (isdigit (new[i]))
  1496. X            digits++;
  1497. X        else if (isupper (new[i]))
  1498. X            uppers++;
  1499. X        else if (islower (new[i]))
  1500. X            lowers++;
  1501. X        else
  1502. X            others++;
  1503. X    }
  1504. X
  1505. X    /*
  1506. X     * The scam is this - a password of only one character type
  1507. X     * must be 8 letters long.  Two types, 7, and so on.
  1508. X     */
  1509. X
  1510. X    size = 9;
  1511. X    if (digits) size--;
  1512. X    if (uppers) size--;
  1513. X    if (lowers) size--;
  1514. X    if (others) size--;
  1515. X
  1516. X    if (size <= i)
  1517. X        return 0;
  1518. X
  1519. X    printf ("Too Simple.  ");
  1520. X    return 1;
  1521. X}
  1522. END_OF_FILE
  1523.   if test 3472 -ne `wc -c <'obscure.c'`; then
  1524.     echo shar: \"'obscure.c'\" unpacked with wrong size!
  1525.   fi
  1526.   # end of 'obscure.c'
  1527. fi
  1528. if test -f 'pwconv.c' -a "${1}" != "-c" ; then 
  1529.   echo shar: Will not clobber existing file \"'pwconv.c'\"
  1530. else
  1531.   echo shar: Extracting \"'pwconv.c'\" \(4445 characters\)
  1532.   sed "s/^X//" >'pwconv.c' <<'END_OF_FILE'
  1533. X/*
  1534. X * Copyright 1989, 1990, 1991, John F. Haugh II
  1535. X * All rights reserved.
  1536. X *
  1537. X * Permission is granted to copy and create derivative works for any
  1538. X * non-commercial purpose, provided this copyright notice is preserved
  1539. X * in all copies of source code, or included in human readable form
  1540. X * and conspicuously displayed on all copies of object code or
  1541. X * distribution media.
  1542. X *
  1543. X * pwconv - convert and update shadow password files
  1544. X *
  1545. X *    Pwconv copies the old password file information to a new shadow
  1546. X *    password file, merging entries from an optional existing shadow
  1547. X *    file.
  1548. X *
  1549. X *    The new password file is left in npasswd, the new shadow file is
  1550. X *    left in nshadow.  Existing shadow entries are copied as is.
  1551. X *    New entries are created with passwords which expire in MAXDAYS days,
  1552. X *    with a last changed date of today, unless password aging
  1553. X *    information was already present.  Likewise, the minimum number of
  1554. X *    days before which the password may be changed is controlled by
  1555. X *    MINDAYS.  The number of warning days is set to WARNAGE if that
  1556. X *    macro exists.  Entries with blank passwordsare not copied to the
  1557. X *    shadow file at all.
  1558. X */
  1559. X
  1560. X#include <sys/types.h>
  1561. X#include <stdio.h>
  1562. X#include <fcntl.h>
  1563. X#include "pwd.h"
  1564. X#ifndef    BSD
  1565. X#include <string.h>
  1566. X#else
  1567. X#define    strchr    index
  1568. X#define    strrchr    rindex
  1569. X#include <strings.h>
  1570. X#endif
  1571. X#include "config.h"
  1572. X#include "shadow.h"
  1573. X
  1574. X#ifndef    lint
  1575. Xstatic    char    _sccsid[] = "@(#)pwconv.c    3.4    07:43:52    9/17/91";
  1576. X#endif
  1577. X
  1578. Xchar    buf[BUFSIZ];
  1579. X
  1580. Xlong    time ();
  1581. Xlong    a64l ();
  1582. Xextern    int    getdef_num();
  1583. X
  1584. Xint    main ()
  1585. X{
  1586. X    long    today;
  1587. X    struct    passwd    *pw;
  1588. X    struct    passwd    *sgetpwent ();
  1589. X    FILE    *pwd;
  1590. X    FILE    *npwd;
  1591. X    FILE    *shadow;
  1592. X    struct    spwd    *spwd;
  1593. X    struct    spwd    tspwd;
  1594. X    int    fd;
  1595. X    char    *cp;
  1596. X
  1597. X    if (! (pwd = fopen (PWDFILE, "r"))) {
  1598. X        perror (PWDFILE);
  1599. X        exit (1);
  1600. X    }
  1601. X    unlink ("npasswd");
  1602. X    if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0 ||
  1603. X            ! (npwd = fdopen (fd, "w"))) {
  1604. X        perror ("npasswd");
  1605. X        exit (1);
  1606. X    }
  1607. X    unlink  ("nshadow");
  1608. X    if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
  1609. X            ! (shadow = fdopen (fd, "w"))) {
  1610. X        perror ("nshadow");
  1611. X        (void) unlink ("npasswd");
  1612. X        (void) unlink ("nshadow");
  1613. X        exit (1);
  1614. X    }
  1615. X
  1616. X    (void) time (&today);
  1617. X    today /= (24L * 60L * 60L);
  1618. X
  1619. X    while (fgets (buf, BUFSIZ, pwd) == buf) {
  1620. X        if (cp = strrchr (buf, '\n'))
  1621. X            *cp = '\0';
  1622. X
  1623. X        if (buf[0] == '#') {    /* comment line */
  1624. X            (void) fprintf (npwd, "%s\n", buf);
  1625. X            continue;
  1626. X        }
  1627. X        if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
  1628. X            (void) fprintf (npwd, "%s\n", buf);
  1629. X            continue;
  1630. X        }
  1631. X        if (pw->pw_passwd[0] == '\0') { /* no password, skip */
  1632. X            (void) fprintf (npwd, "%s\n", buf);
  1633. X            continue;
  1634. X        }
  1635. X        setspent ();        /* rewind old shadow file */
  1636. X
  1637. X        if (spwd = getspnam (pw->pw_name)) {
  1638. X            if (putspent (spwd, shadow)) { /* copy old entry */
  1639. X                perror ("nshadow");
  1640. X                goto error;
  1641. X            }
  1642. X        } else {        /* need a new entry. */
  1643. X            tspwd.sp_namp = pw->pw_name;
  1644. X            tspwd.sp_pwdp = pw->pw_passwd;
  1645. X            pw->pw_passwd = "x";
  1646. X#ifdef    ATT_AGE
  1647. X            if (pw->pw_age) { /* copy old password age stuff */
  1648. X                if (strlen (pw->pw_age) >= 2) {
  1649. X                    tspwd.sp_min = c64i (pw->pw_age[1]);
  1650. X                    tspwd.sp_max = c64i (pw->pw_age[0]);
  1651. X                } else {
  1652. X                    tspwd.sp_min = tspwd.sp_max = -1;
  1653. X                }
  1654. X                if (strlen (pw->pw_age) == 4)
  1655. X                    tspwd.sp_lstchg = a64l (&pw->pw_age[2]);
  1656. X                else
  1657. X                    tspwd.sp_lstchg = -1;
  1658. X
  1659. X                /*
  1660. X                 * Convert weeks to days
  1661. X                 */
  1662. X
  1663. X                if (tspwd.sp_min != -1)
  1664. X                    tspwd.sp_min *= 7;
  1665. X
  1666. X                if (tspwd.sp_max != -1)
  1667. X                    tspwd.sp_max *= 7;
  1668. X
  1669. X                if (tspwd.sp_lstchg != -1)
  1670. X                    tspwd.sp_lstchg *= 7;
  1671. X            } else
  1672. X#endif    /* ATT_AGE */
  1673. X            {    /* fake up new password age stuff */
  1674. X                tspwd.sp_max =
  1675. X                    getdef_num("PASS_MAX_DAYS", 10000);
  1676. X                tspwd.sp_min = getdef_num("PASS_MIN_DAYS", 0);
  1677. X                tspwd.sp_lstchg = today;
  1678. X            }
  1679. X            tspwd.sp_warn = getdef_num("PASS_WARN_AGE", -1);
  1680. X            tspwd.sp_inact = tspwd.sp_expire = tspwd.sp_flag = -1;
  1681. X            if (putspent (&tspwd, shadow)) { /* output entry */
  1682. X                perror ("nshadow");
  1683. X                goto error;
  1684. X            }
  1685. X        }
  1686. X        (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:",
  1687. X                pw->pw_name, pw->pw_passwd,
  1688. X                pw->pw_uid, pw->pw_gid,
  1689. X                pw->pw_gecos, pw->pw_dir);
  1690. X
  1691. X        if (fprintf (npwd, "%s\n",
  1692. X                pw->pw_shell ? pw->pw_shell:"") == EOF) {
  1693. X            perror ("npasswd");
  1694. X            goto error;
  1695. X        }
  1696. X    }
  1697. X    endspent ();
  1698. X
  1699. X    if (ferror (npwd) || ferror (shadow)) {
  1700. X        perror ("pwconv");
  1701. Xerror:
  1702. X        (void) unlink ("npasswd");
  1703. X        (void) unlink ("nshadow");
  1704. X        exit (1);
  1705. X    }
  1706. X    (void) fclose (pwd);
  1707. X    (void) fclose (npwd);
  1708. X    (void) fclose (shadow);
  1709. X
  1710. X    exit (0);
  1711. X}
  1712. END_OF_FILE
  1713.   if test 4445 -ne `wc -c <'pwconv.c'`; then
  1714.     echo shar: \"'pwconv.c'\" unpacked with wrong size!
  1715.   fi
  1716.   # end of 'pwconv.c'
  1717. fi
  1718. if test -f 'setup.c' -a "${1}" != "-c" ; then 
  1719.   echo shar: Will not clobber existing file \"'setup.c'\"
  1720. else
  1721.   echo shar: Extracting \"'setup.c'\" \(4293 characters\)
  1722.   sed "s/^X//" >'setup.c' <<'END_OF_FILE'
  1723. X/*
  1724. X * Copyright 1989, 1990, 1991, John F. Haugh II
  1725. X * All rights reserved.
  1726. X *
  1727. X * Permission is granted to copy and create derivative works for any
  1728. X * non-commercial purpose, provided this copyright notice is preserved
  1729. X * in all copies of source code, or included in human readable form
  1730. X * and conspicuously displayed on all copies of object code or
  1731. X * distribution media.
  1732. X */
  1733. X
  1734. X#include <sys/types.h>
  1735. X#include <stdio.h>
  1736. X#include <utmp.h>
  1737. X
  1738. X#ifdef    BSD
  1739. X#include <strings.h>
  1740. X#define    strchr    index
  1741. X#else
  1742. X#include <string.h>
  1743. X#include <memory.h>
  1744. X#endif
  1745. X
  1746. X#include "config.h"
  1747. X#include "pwd.h"
  1748. X
  1749. X#ifdef    USE_SYSLOG
  1750. X#include <syslog.h>
  1751. X
  1752. X#ifndef    LOG_WARN
  1753. X#define    LOG_WARN    LOG_WARNING
  1754. X#endif
  1755. X#endif
  1756. X
  1757. X#ifndef    lint
  1758. Xstatic    char    sccsid[] = "@(#)setup.c    3.8    07:43:12    9/17/91";
  1759. X#endif
  1760. X
  1761. X#ifndef    SU
  1762. Xextern    struct    utmp    utent;
  1763. X#endif
  1764. X
  1765. Xlong    strtol ();
  1766. X#ifdef    HAVE_ULIMIT
  1767. Xlong    ulimit ();
  1768. X#endif
  1769. X
  1770. Xvoid    addenv ();
  1771. Xextern    char    *getdef_str();
  1772. Xextern    int    getdef_bool();
  1773. Xextern    int    getdef_num();
  1774. X
  1775. X/*
  1776. X * setup - initialize login environment
  1777. X *
  1778. X *    setup() performs the following steps -
  1779. X *
  1780. X *    set the login tty to be owned by the new user ID with TTYPERM modes
  1781. X *    change to the user's home directory
  1782. X *    set the process nice, ulimit, and umask from the password file entry
  1783. X *    set the group ID to the value from the password file entry
  1784. X *    set the supplementary group IDs
  1785. X *    set the user ID to the value from the password file entry
  1786. X *    set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
  1787. X *    variables.
  1788. X */
  1789. X
  1790. Xvoid    setup (info)
  1791. Xstruct    passwd    *info;
  1792. X{
  1793. X    extern    int    errno;
  1794. X    char    buf[BUFSIZ];
  1795. X#ifndef    SU
  1796. X    char    tty[30];
  1797. X#endif
  1798. X    char    *cp;
  1799. X    int    i;
  1800. X    long    l;
  1801. X
  1802. X#ifndef    SU
  1803. X    (void) strcat (strcpy (tty, "/dev/"), utent.ut_line);
  1804. X
  1805. X    if (chown (tty, info->pw_uid, info->pw_gid) ||
  1806. X            chmod (tty, getdef_num("TTYPERM", 0622))) {
  1807. X        (void) sprintf (buf, "Unable to change tty %s", tty);
  1808. X#ifdef    USE_SYSLOG
  1809. X        syslog (LOG_WARN, "unable to change tty `%s' for user `%s'\n",
  1810. X            tty, info->pw_name);
  1811. X        closelog ();
  1812. X#endif
  1813. X        perror (buf);
  1814. X        exit (errno);
  1815. X    }
  1816. X#endif
  1817. X    if (chdir (info->pw_dir) == -1) {
  1818. X        (void) sprintf (buf, "Unable to cd to \"%s\"", info->pw_dir);
  1819. X#ifdef    USE_SYSLOG
  1820. X        syslog (LOG_WARN, "unable to cd to `%s' for user `%s'\n",
  1821. X            info->pw_dir, info->pw_name);
  1822. X        closelog ();
  1823. X#endif
  1824. X        perror (buf);
  1825. X        exit (errno);
  1826. X    }
  1827. X    if ( getdef_bool("QUOTAS_ENAB") ) {
  1828. X        for (cp = info->pw_gecos ; cp != NULL ; cp = strchr (cp, ',')) {
  1829. X            if (*cp == ',')
  1830. X                cp++;
  1831. X
  1832. X            if (strncmp (cp, "pri=", 4) == 0) {
  1833. X                i = atoi (cp + 4);
  1834. X                if (i >= -20 && i <= 20)
  1835. X                    (void) nice (i);
  1836. X
  1837. X                continue;
  1838. X            }
  1839. X#ifdef    HAVE_ULIMIT
  1840. X            if (strncmp (cp, "ulimit=", 7) == 0) {
  1841. X                l = strtol (cp + 7, (char **) 0, 10);
  1842. X                (void) ulimit (2, l);
  1843. X
  1844. X                continue;
  1845. X            }
  1846. X#endif
  1847. X            if (strncmp (cp, "umask=", 6) == 0) {
  1848. X                i = strtol (cp + 6, (char **) 0, 8) & 0777;
  1849. X                (void) umask (i);
  1850. X
  1851. X                continue;
  1852. X            }
  1853. X        }
  1854. X    }
  1855. X    if (setgid (info->pw_gid) == -1) {
  1856. X        puts ("Bad group id");
  1857. X#ifdef    USE_SYSLOG
  1858. X        syslog (LOG_WARN, "bad group ID `%d' for user `%s'\n",
  1859. X            info->pw_gid, info->pw_name);
  1860. X        closelog ();
  1861. X#endif
  1862. X        exit (errno);
  1863. X    }
  1864. X#if NGROUPS > 1
  1865. X    if(initgroups(info->pw_name,info->pw_gid) == -1) {
  1866. X        puts ("initgroups failure");
  1867. X#ifdef    USE_SYSLOG
  1868. X        syslog (LOG_WARN, "initgroups failed for user `%s'\n",
  1869. X            info->pw_name);
  1870. X        closelog ();
  1871. X#endif
  1872. X        exit (errno);
  1873. X    }
  1874. X#endif /* NGROUPS > 1 */
  1875. X#ifndef    BSD
  1876. X    if (setuid (info->pw_uid))
  1877. X#else
  1878. X    if (setreuid (info->pw_uid, info->pw_uid))
  1879. X#endif
  1880. X    {
  1881. X        puts ("Bad user id");
  1882. X#ifdef    USE_SYSLOG
  1883. X        syslog (LOG_WARN, "bad user ID `%d' for user `%s'\n",
  1884. X            info->pw_uid, info->pw_name);
  1885. X        closelog ();
  1886. X#endif
  1887. X        exit (errno);
  1888. X    }
  1889. X    (void) strcat (strcpy (buf, "HOME="), info->pw_dir);
  1890. X    addenv (buf);
  1891. X
  1892. X    if (info->pw_shell == (char *) 0 || ! *info->pw_shell)
  1893. X        info->pw_shell = "/bin/sh";
  1894. X
  1895. X    (void) strcat (strcpy (buf, "SHELL="), info->pw_shell);
  1896. X    addenv (buf);
  1897. X
  1898. X    cp = getdef_str( info->pw_uid == 0 ? "ENV_SUPATH" : "ENV_PATH" );
  1899. X    addenv( cp != NULL ? cp : "PATH=/bin:/usr/bin" );
  1900. X
  1901. X#if defined(BSD) || defined(SUN)
  1902. X    (void) strcat (strcpy (buf, "USER="), info->pw_name);
  1903. X#else
  1904. X    (void) strcat (strcpy (buf, "LOGNAME="), info->pw_name);
  1905. X#endif /* BSD || SUN */
  1906. X    addenv (buf);
  1907. X
  1908. X    if ( (cp=getdef_str("MAIL_DIR")) == NULL )
  1909. X        cp = "/usr/spool/mail";
  1910. X    (void) strcat (strcat (strcat (strcpy (buf,
  1911. X        "MAIL="), cp), "/"), info->pw_name);
  1912. X    addenv (buf);
  1913. X}
  1914. END_OF_FILE
  1915.   if test 4293 -ne `wc -c <'setup.c'`; then
  1916.     echo shar: \"'setup.c'\" unpacked with wrong size!
  1917.   fi
  1918.   # end of 'setup.c'
  1919. fi
  1920. if test -f 'sulogin.c' -a "${1}" != "-c" ; then 
  1921.   echo shar: Will not clobber existing file \"'sulogin.c'\"
  1922. else
  1923.   echo shar: Extracting \"'sulogin.c'\" \(3355 characters\)
  1924.   sed "s/^X//" >'sulogin.c' <<'END_OF_FILE'
  1925. X/*
  1926. X * Copyright 1989, 1990, 1991, John F. Haugh II
  1927. X * All rights reserved.
  1928. X *
  1929. X * Permission is granted to copy and create derivative works for any
  1930. X * non-commercial purpose, provided this copyright notice is preserved
  1931. X * in all copies of source code, or included in human readable form
  1932. X * and conspicuously displayed on all copies of object code or
  1933. X * distribution media.
  1934. X */
  1935. X
  1936. X#include <sys/types.h>
  1937. X#include <stdio.h>
  1938. X#include "pwd.h"
  1939. X#include <utmp.h>
  1940. X#ifdef    BSD
  1941. X#include <strings.h>
  1942. X#define    strchr    index
  1943. X#define    strrchr    rindex
  1944. X#else
  1945. X#include <string.h>
  1946. X#include <memory.h>
  1947. X#endif
  1948. X#include "config.h"
  1949. X
  1950. X#ifndef    lint
  1951. Xstatic    char    sccsid[] = "@(#)sulogin.c    3.7    07:43:27    9/17/91";
  1952. X#endif
  1953. X
  1954. Xchar    name[BUFSIZ];
  1955. Xchar    pass[BUFSIZ];
  1956. Xchar    home[BUFSIZ];
  1957. Xchar    prog[BUFSIZ];
  1958. Xchar    mail[BUFSIZ];
  1959. X
  1960. Xstruct    passwd    pwent;
  1961. Xstruct    utmp    utent;
  1962. X
  1963. X#ifndef    MAXENV
  1964. X#define    MAXENV    64
  1965. X#endif
  1966. X
  1967. Xchar    *newenvp[MAXENV];
  1968. Xint    newenvc = 0;
  1969. Xint    maxenv = MAXENV;
  1970. Xextern    char    **environ;
  1971. Xextern    char    *getpass();
  1972. X
  1973. Xextern    char    *getdef_str();
  1974. X
  1975. X#ifndef    ALARM
  1976. X#define    ALARM    60
  1977. X#endif
  1978. X
  1979. X#ifndef    RETRIES
  1980. X#define    RETRIES    3
  1981. X#endif
  1982. X
  1983. X/*ARGSUSED*/
  1984. Xint    main (argc, argv, envp)
  1985. Xint    argc;
  1986. Xchar    **argv;
  1987. Xchar    **envp;
  1988. X{
  1989. X    char    *getenv ();
  1990. X    char    *ttyname ();
  1991. X    char    *getpass ();
  1992. X    char    *tz ();
  1993. X    char    *cp;
  1994. X
  1995. X    if (access (PWDFILE, 0) == -1) { /* must be a password file! */
  1996. X        printf ("No password file\n");
  1997. X        exit (1);
  1998. X    }
  1999. X#ifdef    NDEBUG
  2000. X    if (getppid () != 1)        /* parent must be INIT */
  2001. X        exit (1);
  2002. X#endif
  2003. X    if (! isatty (0) || ! isatty (1) || ! isatty (2))
  2004. X        exit (1);        /* must be a terminal */
  2005. X
  2006. X    while (*envp)            /* add inherited environment, */
  2007. X        addenv (*envp++);    /* some variables change later */
  2008. X
  2009. X    if (cp = getdef_str("ENV_TZ"))
  2010. X        addenv (*cp == '/' ? tz(cp) : cp);
  2011. X    if (cp = getdef_str("ENV_HZ"))
  2012. X        addenv (cp);        /* set the default $HZ, if one */
  2013. X    (void) strcpy (name, "root");    /* KLUDGE!!! */
  2014. X
  2015. X    alarm (ALARM);        /* only wait so long ... */
  2016. X    while (1) {        /* repeatedly get login/password pairs */
  2017. X        entry (name, &pwent);    /* get entry from password file */
  2018. X        if (pwent.pw_name == (char *) 0) {
  2019. X            printf ("No password entry for 'root'\n");
  2020. X            exit (1);
  2021. X        }
  2022. X
  2023. X    /*
  2024. X     * Here we prompt for the root password, or if no password is
  2025. X     * given we just exit.
  2026. X     */
  2027. X
  2028. X                    /* get a password for root */
  2029. X        if (! (cp = getpass ("Type control-d for normal startup,\n\
  2030. X(or give root password for system maintenance):")))
  2031. X            exit (0);
  2032. X        else
  2033. X            strcpy (pass, cp);
  2034. X
  2035. X        if (valid (pass, &pwent)) /* check encrypted passwords ... */
  2036. X            break;        /* ... encrypted passwords matched */
  2037. X
  2038. X        puts ("Login incorrect");
  2039. X    }
  2040. X    alarm (0);
  2041. X    environ = newenvp;        /* make new environment active */
  2042. X
  2043. X    puts ("Entering System Maintenance Mode");
  2044. X
  2045. X    /*
  2046. X     * Normally there would be a utmp entry for login to mung on
  2047. X     * to get the tty name, date, etc. from.  We don't need all that
  2048. X     * stuff because we won't update the utmp or wtmp files.  BUT!,
  2049. X     * we do need the tty name so we can set the permissions and
  2050. X     * ownership.
  2051. X     */
  2052. X
  2053. X    if (cp = ttyname (0)) {        /* found entry in /dev/ */
  2054. X        if (strrchr (cp, '/') != (char *) 0)
  2055. X            strcpy (utent.ut_line, strrchr (cp, '/') + 1);
  2056. X        else
  2057. X            strcpy (utent.ut_line, cp);
  2058. X    }
  2059. X    if (getenv ("IFS"))        /* don't export user IFS ... */
  2060. X        addenv ("IFS= \t\n");    /* ... instead, set a safe IFS */
  2061. X
  2062. X    setup (&pwent);            /* set UID, GID, HOME, etc ... */
  2063. X
  2064. X    shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
  2065. X    /*NOTREACHED*/
  2066. X}
  2067. END_OF_FILE
  2068.   if test 3355 -ne `wc -c <'sulogin.c'`; then
  2069.     echo shar: \"'sulogin.c'\" unpacked with wrong size!
  2070.   fi
  2071.   # end of 'sulogin.c'
  2072. fi
  2073. if test -f 'useradd.1' -a "${1}" != "-c" ; then 
  2074.   echo shar: Will not clobber existing file \"'useradd.1'\"
  2075. else
  2076.   echo shar: Extracting \"'useradd.1'\" \(4618 characters\)
  2077.   sed "s/^X//" >'useradd.1' <<'END_OF_FILE'
  2078. X.\" Copyright 1991, John F. Haugh II
  2079. X.\" All rights reserved.
  2080. X.\"
  2081. X.\" Permission is granted to copy and create derivative works for any
  2082. X.\" non-commercial purpose, provided this copyright notice is preserved
  2083. X.\" in all copies of source code, or included in human readable form
  2084. X.\" and conspicuously displayed on all copies of object code or
  2085. X.\" distribution media.
  2086. X.\"
  2087. X.\"    @(#)useradd.1    3.1    07:45:46    7/13/91
  2088. X.\"
  2089. X.TH USERADD 1M
  2090. X.SH NAME
  2091. Xuseradd \- Create a new user or update default new user information
  2092. X.SH SYNOPSIS
  2093. X.B useradd
  2094. X[ \fB-c\fI comment\fR ]
  2095. X[ \fB-d\fI home_dir\fR ]
  2096. X[ \fB-e\fI expire_date\fR ]
  2097. X[ \fB-f\fI inactive_time\fR ]
  2098. X[ \fB-g\fI initial_group\fR ]
  2099. X[ \fB-G\fI group[,...]\fR ]
  2100. X[ \fB-m\fR [ \fB-k\fI skeleton_dir\fR ] ]
  2101. X[ \fB-s\fI shell\fR ]
  2102. X[ \fB-u\fI uid \fR[ \fB-o\fR ] ]
  2103. X.I login
  2104. X.sp 1
  2105. X.B useradd
  2106. X\fB-D\fR
  2107. X[ \fB-g\fI default_group\fR ]
  2108. X[ \fB-b\fI default_home\fR ]
  2109. X[ \fB-f\fI default_inactive\fR ]
  2110. X[ \fB-e\fI default_exiration\fR ]
  2111. X.SH DESCRIPTION
  2112. X.SS Creating New Users
  2113. XWhen invoked without the \fB-D\fR option, the \fIuseradd\fR command
  2114. Xcreates a new user account using the values specified on the
  2115. Xcommand line and the default values from the system.
  2116. XThe new user account will be entered into the system files as needed,
  2117. Xthe home directory will be created, and initial files copied, depending
  2118. Xon the command line options.
  2119. XThe options which apply to the \fIuseradd\fR command are
  2120. X.IP "\fB-d \fIhome_dir\fR"
  2121. XThe new user will be created using \fIhome_dir\fR as the value for
  2122. Xthe user's login directory.
  2123. XThe default is to append the \fIlogin\fR name to \fIdefault_home\fR
  2124. Xand use that as the login directory name.
  2125. X.IP "\fB-e \fIexpire_date\fR"
  2126. XThe date on which the user account will be disabled.
  2127. XThe date is specified in the format \fIMM/DD/YY\fR.
  2128. X.IP "\fB-f \fIinactive_days\fR"
  2129. XThe number of days after a password expires until the account
  2130. Xis permanently disabled.
  2131. XA value of 0 disables the account as soon as the password has
  2132. Xexpired, and a value of -1 disables the feature.
  2133. XThe default value is -1.
  2134. X.IP "\fB-g \fIinitial_group\fR"
  2135. XThe group name or number of the user's initial login group.
  2136. XThe group name must exist.  A group number must refer to an
  2137. Xalready existing group.
  2138. XThe default group number is 1.
  2139. X.IP "\fB-G \fIgroup,[...]\fR"
  2140. XA list of supplementary groups which the user is also a member
  2141. Xof.
  2142. XEach group is separated from the next by a comma, with no
  2143. Xintervening whitespace.
  2144. XThe groups are subject to the same restrictions as the group
  2145. Xgiven with the \fB-g\fR option.
  2146. XThe default is for the user to belong only to the initial group.
  2147. X.IP \fB-m\fR
  2148. XThe user's home directory will be created if it does not exist.
  2149. XThe files contained in \fIskeleton_dir\fR will be copied to the
  2150. Xhome directory if the \fB-k\fR option is used.
  2151. XThe \fB-k\fR option is only valid in conjunction with the \fB-m\fR
  2152. Xoption.
  2153. XThe default is to not create the directory and to not copy any
  2154. Xfiles.
  2155. X.IP "\fB-s \fIshell\fR"
  2156. XThe name of the user's login shell.
  2157. XThe default is to leave this field blank, which causes the system
  2158. Xto select the default login shell.
  2159. X.IP "\fB-u \fIuid\fR"
  2160. XThe numerical value of the user's ID.
  2161. XThis value must be unique, unless the \fI-o\fR option is used.
  2162. XThe value must be non-negative.
  2163. XThe default is to use the smallest ID value greater than 99 and
  2164. Xgreater than every other user.
  2165. XValues between 0 and 99 are typically reserved for system accounts.
  2166. X.SS Changing the default values
  2167. XWhen invoked with the \fB-D\fR option, \fIuseradd\fR will either
  2168. Xdisplay the current default values, or update the default values
  2169. Xfrom the command line.
  2170. XThe valid options are
  2171. X.IP "\fB-b \fIdefault_home\fR"
  2172. XThe initial path prefix for a new user's home directory.
  2173. XThe user's name will be affixed to the end of \fIdefault_home\fR
  2174. Xto create the new directory name if the \fB-d\fI option is not
  2175. Xused when creating a new account.
  2176. X.IP "\fB-e \fIdefault_expire\fR"
  2177. XThe number of days after a password is changed before it must
  2178. Xbe changed again.
  2179. X.IP "\fB-f \fIdefault_inactive\fR"
  2180. XThe number of days after a password has expired before the
  2181. Xaccount will be disabled.
  2182. X.IP "\fB-g \fIdefault_group\fR"
  2183. XThe group name or ID for a new user's initial group.
  2184. XThe named group must exist, and a numerical group ID must have
  2185. Xan existing entry .
  2186. X.PP
  2187. XIf no options are specified, \fIuseradd\fR displays the current
  2188. Xdefault values.
  2189. X.SH Files
  2190. X/etc/passwd \- user account information
  2191. X.br
  2192. X/etc/shadow \- secure user account information
  2193. X.br
  2194. X/etc/group \- group information
  2195. X.br
  2196. X/etc/defaults/useradd \- default information
  2197. X.SH SEE ALSO
  2198. X\fBchfn(1), chsh(1), groupadd(1M), groupdel(1M), groupmod(1M),
  2199. Xpasswd(1), userdel(1M), usermod(1M)
  2200. END_OF_FILE
  2201.   if test 4618 -ne `wc -c <'useradd.1'`; then
  2202.     echo shar: \"'useradd.1'\" unpacked with wrong size!
  2203.   fi
  2204.   # end of 'useradd.1'
  2205. fi
  2206. if test -f 'utmp.c' -a "${1}" != "-c" ; then 
  2207.   echo shar: Will not clobber existing file \"'utmp.c'\"
  2208. else
  2209.   echo shar: Extracting \"'utmp.c'\" \(4259 characters\)
  2210.   sed "s/^X//" >'utmp.c' <<'END_OF_FILE'
  2211. X/*
  2212. X * Copyright 1989, 1990, 1991, John F. Haugh II
  2213. X * All rights reserved.
  2214. X *
  2215. X * Permission is granted to copy and create derivative works for any
  2216. X * non-commercial purpose, provided this copyright notice is preserved
  2217. X * in all copies of source code, or included in human readable form
  2218. X * and conspicuously displayed on all copies of object code or
  2219. X * distribution media.
  2220. X */
  2221. X
  2222. X#include <sys/types.h>
  2223. X#include <utmp.h>
  2224. X#include <fcntl.h>
  2225. X#ifndef    BSD
  2226. X#include <string.h>
  2227. X#include <memory.h>
  2228. X#define    bzero(a,n)    memset(a, 0, n)
  2229. X#else
  2230. X#include <strings.h>
  2231. X#define    strchr    index
  2232. X#define    strrchr    rindex
  2233. X#endif
  2234. X#include <stdio.h>
  2235. X#include "config.h"
  2236. X
  2237. X#if defined(SUN) || defined(BSD)
  2238. X#ifndef    WTMP_FILE
  2239. X#define WTMP_FILE "/usr/adm/wtmp"
  2240. X#endif
  2241. X#endif    /* SUN || BSD */
  2242. X
  2243. X#ifndef    lint
  2244. Xstatic    char    sccsid[] = "@(#)utmp.c    3.12    07:43:36    9/17/91";
  2245. X#endif
  2246. X
  2247. Xextern    struct    utmp    utent;
  2248. X
  2249. Xextern    struct    utmp    *getutent();
  2250. Xextern    struct    utmp    *getutline();
  2251. Xextern    void    setutent();
  2252. Xextern    void    endutent();
  2253. Xextern    time_t    time();
  2254. Xextern    char    *ttyname();
  2255. Xextern    long    lseek();
  2256. X
  2257. X#define    NO_UTENT \
  2258. X    "No utmp entry.  You must exec \"login\" from the lowest level \"sh\""
  2259. X#define    NO_TTY \
  2260. X    "Unable to determine your tty name."
  2261. X
  2262. X/*
  2263. X * checkutmp - see if utmp file is correct for this process
  2264. X *
  2265. X *    System V is very picky about the contents of the utmp file
  2266. X *    and requires that a slot for the current process exist.
  2267. X *    The utmp file is scanned for an entry with the same process
  2268. X *    ID.  If no entry exists the process exits with a message.
  2269. X *
  2270. X *    The "picky" flag is for network and other logins that may
  2271. X *    use special flags.  It allows the pid checks to be overridden.
  2272. X *    This means that getty should never invoke login with any
  2273. X *    command line flags.
  2274. X */
  2275. X
  2276. Xvoid
  2277. Xcheckutmp (picky)
  2278. Xint    picky;
  2279. X{
  2280. X    char    *line;
  2281. X#ifdef    USG
  2282. X    struct    utmp    *ut;
  2283. X#ifndef    NDEBUG
  2284. X    int    pid = getppid ();
  2285. X#else
  2286. X    int    pid = getpid ();
  2287. X#endif
  2288. X#endif
  2289. X
  2290. X#ifndef    SUN
  2291. X    setutent ();
  2292. X#endif    /* SUN */
  2293. X
  2294. X#ifdef    USG
  2295. X    if (picky) {
  2296. X        while (ut = getutent ())
  2297. X            if (ut->ut_pid == pid)
  2298. X                break;
  2299. X
  2300. X        if (ut)
  2301. X            utent = *ut;
  2302. X
  2303. X        endutent ();
  2304. X
  2305. X        if (! ut || utent.ut_pid != pid) {
  2306. X             (void) puts (NO_UTENT);
  2307. X            exit (1);
  2308. X        }
  2309. X        if (utent.ut_line[0] == '\0') {
  2310. X            if (! (line = ttyname (0))) {
  2311. X                (void) puts (NO_TTY);
  2312. X                exit (1);
  2313. X            }
  2314. X            if (strncmp (line, "/dev/", 5) == 0)
  2315. X                line += 5;
  2316. X            (void) strncpy (utent.ut_line, line,
  2317. X                    (int) sizeof utent.ut_line);
  2318. X        }
  2319. X    } else {
  2320. X        if (! (line = ttyname (0))) {
  2321. X            puts (NO_TTY);
  2322. X            exit (1);
  2323. X        }
  2324. X        if (strncmp (line, "/dev/", 5) == 0)
  2325. X            line += 5;
  2326. X
  2327. X         (void) strncpy (utent.ut_line, line,
  2328. X                          (int) sizeof utent.ut_line);
  2329. X        if (ut = getutline (&utent))
  2330. X             (void) strncpy (utent.ut_id, ut->ut_id,
  2331. X                     (int) sizeof ut->ut_id);
  2332. X
  2333. X        (void) strcpy (utent.ut_user, "LOGIN");
  2334. X        utent.ut_pid = getpid ();
  2335. X        utent.ut_type = LOGIN_PROCESS;
  2336. X        (void) time (&utent.ut_time);
  2337. X    }
  2338. X#else    /* !USG */
  2339. X    bzero (&utent, sizeof utent);
  2340. X    if (! (line = ttyname (0))) {
  2341. X        puts (NO_TTY);
  2342. X        exit (1);
  2343. X    }
  2344. X    if (strncmp (line, "/dev/", 5))
  2345. X        line += 5;
  2346. X
  2347. X    (void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
  2348. X    (void) time (&utent.ut_time);
  2349. X#endif    /* !USG */
  2350. X}
  2351. X
  2352. X/*
  2353. X * setutmp - put a USER_PROCESS entry in the utmp file
  2354. X *
  2355. X *    setutmp changes the type of the current utmp entry to
  2356. X *    USER_PROCESS.  the wtmp file will be updated as well.
  2357. X */
  2358. X
  2359. Xvoid
  2360. Xsetutmp (name, line)
  2361. Xchar    *name;
  2362. Xchar    *line;
  2363. X{
  2364. X    struct    utmp    utmp;
  2365. X    int    fd;
  2366. X    int    found = 0;
  2367. X
  2368. X    if (! (fd = open ("/etc/utmp", O_RDWR)))
  2369. X        return;
  2370. X
  2371. X     while (! found && read (fd, &utmp, sizeof utmp) == sizeof utmp) {
  2372. X         if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
  2373. X            found++;
  2374. X    }
  2375. X    if (! found) {
  2376. X          (void) bzero (&utmp, sizeof utmp);
  2377. X         (void) strncpy (utmp.ut_line, line, (int) sizeof utmp.ut_line);
  2378. X    }
  2379. X#if defined(SUN) || defined(BSD)
  2380. X    (void) strncpy (utmp.ut_name, name, (int) sizeof utent.ut_name);
  2381. X#else    /* SUN */
  2382. X     (void) strncpy (utmp.ut_user, name, (int) sizeof utent.ut_user);
  2383. X    utmp.ut_type = USER_PROCESS;
  2384. X    utmp.ut_pid = getpid ();
  2385. X#endif    /* SUN || BSD */
  2386. X    (void) time (&utmp.ut_time);
  2387. X
  2388. X    if (found)
  2389. X        lseek (fd, (long) - sizeof utmp, 1);
  2390. X
  2391. X    (void) write (fd, &utmp, sizeof utmp);
  2392. X    (void) close (fd);
  2393. X
  2394. X    if ((fd = open (WTMP_FILE, O_WRONLY|O_APPEND)) >= 0) {
  2395. X        (void) write (fd, &utmp, sizeof utmp);
  2396. X        (void) close (fd);
  2397. X    }
  2398. X     utent = utmp;
  2399. X}
  2400. END_OF_FILE
  2401.   if test 4259 -ne `wc -c <'utmp.c'`; then
  2402.     echo shar: \"'utmp.c'\" unpacked with wrong size!
  2403.   fi
  2404.   # end of 'utmp.c'
  2405. fi
  2406. echo shar: End of archive 8 \(of 11\).
  2407. cp /dev/null ark8isdone
  2408. MISSING=""
  2409. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2410.     if test ! -f ark${I}isdone ; then
  2411.     MISSING="${MISSING} ${I}"
  2412.     fi
  2413. done
  2414. if test "${MISSING}" = "" ; then
  2415.     echo You have unpacked all 11 archives.
  2416.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2417. else
  2418.     echo You still must unpack the following archives:
  2419.     echo "        " ${MISSING}
  2420. fi
  2421. exit 0
  2422. exit 0 # Just in case...
  2423.